' xml viewer

Strict

Import "../maxtk/maxtk.bmx"

Import "minixml.bmx"


Type TXMLOptions Extends TOptionsPage

	Field	owner:TXMLPlugin	
	Field	tabsize:TNumberButton
	Field	editcolor:TColorButton
	Field	editfont:TFontButton
	Field	editstyle:TTextStyle
	Field	styles:TTextStyle[4]
		
	Method Dirty(cause:TDataNode)
'		owner.ResetOptions
'		If cause=blitzpluspath And Proceed("Import BlitzPlus Settings?") ImportXMLPrefs  blitzpluspath.path
		super.Dirty cause
	End Method
	
	Function HexToDec( hexcode$ )
		Local l,v,d
		hexcode=hexcode.toupper()
		While hexcode
			d=Asc(hexcode[..1])
			If d<65 d=d-48 Else d=d-55
			v=v*16+d
			hexcode=hexcode[1..]
		Wend
		Return v
	End Function

	Method CreateXMLOptions:TXMLOptions(plugin:TXMLPlugin)
		SetName "XML Options"
		owner=plugin
		plugin.editor.hostoptions.AddPage Self
		tabsize=AddNumberButton("Tab Size",4)
		editcolor=AddColorButton("Edit Color",-1)
		editfont=AddFontButton("Edit Font","Courier",12,0)
		editstyle=AddTextStyle(Self,"Style")'ComboButton("Style",["Normal","Bold","Italic","Bold+Italic"])
		styles=New TTextStyle[4]
		styles[0]=AddTextStyle(Self,"Default")
		styles[1]=AddTextStyle(Self,"Remarks")
		styles[2]=AddTextStyle(Self,"Strings")
		styles[3]=AddTextStyle(Self,"Tokens")
		Layout
		Return Self
	End Method

End Type

Type TXMLPlugin Extends TPlugin
	Field	editor:TEditor
	Field	options:TXMLOptions
'	Field	editmenu:TGadget

	Method Open:Object(path$)
		path=host.FullPath(path)
		Return TXMLView.Open(Self,path)
	End Method
	
	Method Initialize(owner:THost)
		host=owner
		SetName("XML",["xml","dae","xsd"])
		editor=TEditor(host)
		If Not editor RuntimeError "EntityPlugin requires TEditor Host"
		options=New TXMLOptions.CreateXMLOptions(Self)
'		editmenu=CreateEditMenu()
	End Method

End Type

Type TXMLNode Extends TDataNode
	Field	_owner:TXMLFile
	Field	_element:TElement
	
	Method Invoke(command$,argument:Object=Null)
		Select command
			Case "ACTIVATE"
'				owner.ShowPos(pos)
		End Select
	End Method

	Method Sync(snap:TDataNode)
		Local	n:TXMLNode		
'		If snap.name<>name SetName(snap.name)
'		If snap._element<>_element SetElement(snap._element)
		n=TXMLNode(snap)
		If n SetElement n._element		
'_element=n._element
		Super.Sync(snap)
	End Method
	
	Method SetElement(e:TElement)
		Local n$,d$
		_element=e
'		Local	p
'		p=n.find("'")
'		If p<>-1 n=n[..p]
		n=_element.ToString().Trim()		
		e.Evaluate()
		d$=e.ObjectValue(e.Value)
		SetName n+d
'		name=n.Trim()
	End Method
		
	Method AttachKids()
		Local o:Object
		Local e:TElement
		Local n:TXMLNode
		For o=EachIn _element.content
			e=TElement(o)
			If e
				n=New TXMLNode.CreateEntityNodes(_owner,e)
				Append n
'				n.AttachKids
			EndIf
		Next
		Open
	End Method
	
	Method CreateEntityNodes:TXMLNode(owner:TXMLFile,element:TElement)
		_owner=owner
		SetElement element
		AttachKids
		Return Self		
	End Method
	
End Type

Type TXMLFile
	Field _path$
	Field _rootelement:TElement
	Field _schema:TElement
	Field _syncnode:TDataNode

	Method GetNode:TDataNode()		
		Local	root:TDataNode
		Local	node:TDataNode				
		root=New TDataNode.Create(StripDir(_path))
		If _rootelement 
			node=New TXMLNode.CreateEntityNodes(Self,_rootelement)
			root.Append node
		EndIf		
		If _syncnode
			_syncnode.Sync(root)	
			root.Free
		Else
			_syncnode=root
		EndIf
		Return _syncnode
	End Method

	Method Create:TXMLFile(path$,root:TElement)
		_path=path
		_rootelement=root
		root.Evaluate
		Return Self
	End Method

	Function Open:TXMLFile(path$)
		Local src$
		Local root:TElement
		src=LoadText(path)
		If src root=ParseXML(src)
		If root Return New TXMLFile.Create(path,root)
	End Function
End Type


Rem ttoolpanel
	Field	name$,path$
	Field	panel:TGadget
	Field	index
	Field	active
EndRem

Type TXMLView Extends TToolPanel
	
	Field _plugin:TXMLPlugin
' interface
	Field _source:TXMLFile
	Field _target:TXMLFile
	Field _nodeview:TNodeView

	Method Create:TXMLView(plugin:TXMLPlugin,source:TXMLFile)
		Local host:THost
		Local node:TDataNode

		_plugin=plugin
		_source=source

		host=plugin.host
		path=source._path
		name=StripDir(path)
		host.AddPanel Self
		
		node=source.GetNode()
		_nodeview=TNodeView.CreateNodeView(panel,node)
		
		SetGadgetLayout _nodeview.treeview,1,1,1,1		

		Local troot:TGadget=TreeViewRoot(_nodeview.treeview)
		node.setnode troot,_nodeview.viewindex

		Return Self
	End Method

	Function Open:TXMLView(plugin:TXMLPlugin,path$)
		Local xmlfile:TXMLFile
		xmlfile=TXMLFile.Open(path)
		If xmlfile Return New TXMLView.Create(plugin,xmlfile)
	End Function

	Method Refresh()
		Local	rgb:TColorButton
		Local	treeview:TGadget
		
		Local	options:TXMLOptions		
		options=_plugin.options
		treeview=_nodeview.treeview
'		SetTextAreaTabs textarea,options.tabsize.value
		SetTextAreaFont treeview,options.editfont.font
		rgb=options.editcolor
		SetTextAreaColor treeview,rgb.red,rgb.green,rgb.blue,True
		rgb=options.editstyle.color
		SetTextAreaColor treeview,rgb.red,rgb.green,rgb.blue,False
	End Method

	Method Invoke(command$,argument:Object=Null)
		Local	file$,ex$
		Local	p,res
		Select command
			Case "SHOW"
'				If canvas ActivateGadget canvas
				_plugin.host.SetTitle path				
'				_plugin.host.SetCodeNode GetNode()
				ActivateGadget _nodeview.treeview
			Case "CLOSE"
				_plugin.host.RemovePanel Self
			Case "ACTIVATE"
				ActivateGadget _nodeview.treeview
			Case "REFRESH"
				Refresh
		End Select
	End Method

	Method OnEvent()
		Select EventID()
'		Case EVENT_TIMERTICK
		End Select
	End Method

End Type

' plugin interface

'	,file$,root:TElement)



Rem
		Local xmldir$
		Local xmlfile$
		Local olddir$
		Local src$		
		
		If FileType(path)<>FILETYPE_FILE Return
		olddir=CurrentDir$()		
		xmldir=ExtractDir(RealPath(path))
		ChangeDir xmldir
		root=LoadXML( path )
		ChangeDir olddir
EndRem


Rem
	,root:TElement)
		_path=path
		_rootelement=root
		Local rootnode:TDataNode=GetNode()
		_nodeview=TNodeView.CreateNodeView(panel,rootnode)
		SetGadgetLayout _nodeview.treeview,1,1,1,1		
	'	CreateTreeView(0,0,ClientWidth(panel),ClientHeight(panel),panel,0)		
		Local troot:TGadget=TreeViewRoot(_nodeview.treeview)
		_rootnode.setnode troot,_nodeview.viewindex
		Return Self
	End Method

		Local host:THost
		host=plugin.host
		path=host.FullPath(file)		
		name=StripDir(path)
		host.AddPanel Self

	Method OnEvent()
		Select EventID()
'		Case EVENT_TIMERTICK
		End Select
	End Method

EndRem

Rem

Type TXMLFile
	Field _path$
	Field _rootelement:TElement
	Field _schema:TElement
	Field _syncnode:TDataNode		'latest version of the element tree

'	latesti am the root node
'	Field _nodeview:TNodeView

	Function ReadXML:TElement(file$)
		Local root:TElement
		Local src$		
		src=LoadText(file)
		root=ParseXML(src)
		root.Evaluate
		Return root
	End Function	

	Method Create:TXMLFile(path$,root:TElement)
		_path=path
		_rootelement=root
		Local rootnode:TDataNode=GetNode()

		_nodeview=TNodeView.CreateNodeView(panel,rootnode)
		SetGadgetLayout _nodeview.treeview,1,1,1,1		
	'	CreateTreeView(0,0,ClientWidth(panel),ClientHeight(panel),panel,0)		
		Local troot:TGadget=TreeViewRoot(_nodeview.treeview)
		_rootnode.setnode troot,_nodeview.viewindex
		Return Self
	End Method
	
	Method Refresh()
		Local	rgb:TColorButton
		Local	treeview:TGadget
		
		Local	options:TXMLOptions		
		options=_plugin.options
		treeview=_nodeview.treeview
'		SetTextAreaTabs textarea,options.tabsize.value
		SetTextAreaFont treeview,options.editfont.font
		rgb=options.editcolor
		SetTextAreaColor treeview,rgb.red,rgb.green,rgb.blue,True
		rgb=options.editstyle.color
		SetTextAreaColor treeview,rgb.red,rgb.green,rgb.blue,False
	End Method

	Method GetNode:TDataNode()		
		Local	root:TDataNode
		Local	node:TDataNode
				
		root=New TDataNode.Create(StripDir(path))
		
		If _rootelement 
			node=New TXMLNode.CreateEntityNodes(Self,_rootelement)
			root.Append node
		EndIf
		
		If _rootnode
			_rootnode.Sync(root)	
			root.Free
		Else
			_rootnode=root
		EndIf
		Return _rootnode
	End Method

End Type

Type TXMLView Extends TToolPanel
	
	Field _plugin:TXMLPlugin
' interface
	Field _source:TXMLFile
	Field _target:TXMLFile

	Field _nodeview:TNodeView


	Function Open:TXMLView(plugin:TXMLPlugin,path$)
		Local	root:TElement
		Local	view:TXMLView	
		Local	xmldir$,olddir$
		olddir=CurrentDir$()		
		xmldir=ExtractDir(RealPath(path))
		ChangeDir xmldir	
		root=LoadXML( path )		
		ChangeDir olddir
		If Not root Return Null		
		view=New TXMLView.Create(plugin,path$,root)
		Return view
	End Function

	Method Create:TXMLView(plugin:TXMLPlugin,file$,root:TElement)
		Local host:THost

		_plugin=plugin
		host=plugin.host
		path=host.FullPath(file)		
		name=StripDir(path)
		_rootelement=root
		
		host.AddPanel Self

		Local rootnode:TDataNode=GetNode()
		_nodeview=TNodeView.CreateNodeView(panel,rootnode)
		
		SetGadgetLayout _nodeview.treeview,1,1,1,1		
	'	CreateTreeView(0,0,ClientWidth(panel),ClientHeight(panel),panel,0)		

		Local troot:TGadget=TreeViewRoot(_nodeview.treeview)
		_rootnode.setnode troot,_nodeview.viewindex

		Return Self
	End Method
	

	Method Invoke(command$,argument:Object=Null)
		Local	file$,ex$
		Local	p,res
		Select command
			Case "SHOW"
'				If canvas ActivateGadget canvas
				_plugin.host.SetTitle path				
'				_plugin.host.SetCodeNode GetNode()
				ActivateGadget _nodeview.treeview
			Case "CLOSE"
				_plugin.host.RemovePanel Self
			Case "ACTIVATE"
				ActivateGadget _nodeview.treeview
			Case "REFRESH
				Refresh
		End Select
	End Method


End Type

		Local host:THost
		host=plugin.host
		path=host.FullPath(file)		
		name=StripDir(path)
		host.AddPanel Self

	Method OnEvent()
		Select EventID()
'		Case EVENT_TIMERTICK
		End Select
	End Method

EndRem

Rem
Function LoadXML(url:Object)
	Local root:TElement
	Local schema:TElement
	Local src$

	src=LoadText("COLLADASchema_141.xsd")
	schema=ParseXML(src)
	DebugLog "**schema**~n"+schema.ToString()

	src=LoadText(url)
'	DebugLog src
	root=ParseXML(src)
'	DebugLog "******root.ToString************"
	root.Evaluate
	DebugLog "**root**~n"+root.ToString()
End Function
EndRem

'LoadCollada("cube.DAE")


Rem

'Return ParseXML(data)
' bail on empty tag
		If n$
' skip comments
		If n$[0..1]="?" Return ParseXML(data)
' get name 
	EndIf
		
		
	EndIf
		If n ParseXML n,element			

	
	
	p=data.find("<",pos)+1
	If p=0 Return
	q=data.find(">",p)
	If q=-1 Return
	n$=data[p..q].Trim()


'	data=data[q+1..]	
' bail on empty tag
	If n$="" Return
' skip comments
	If n$[0..1]="?" Return ParseXML(data)
' get name 
	p=n.find(" ")
	If p<>-1
		a$=n[p+1..].Trim()
		n=n[..p]
	EndIf
	element=New TElement
	element.name=n
	If current 
		current.content.AddLast element
		element.parent=current
	EndIf
' read attributes
	While a
		p=a.find("=")
		If p=-1 Exit
		n=a[..p]
		a=a[p+1..].Trim()
		If a[..1]="~q"
			a=a[1..]
			p=a.find("~q")
		Else
			p=a.find(" ",1)
		EndIf
		If p=-1 p=Len a
		v$=a[..p]
		a=a[p+1..]
		element.attributes.AddLast TAttribute.Create(n,v)		
	Wend	
' read content
	While data
	
	Wend
	Return element
End Function

		p=data.find("<")
		If p<>0
			If p=-1 p=Len data
			n=data[..p].Trim()	
			data=data[p..]
			If n element.content.AddLast n
		Else
			q=data.find(">",p)
			If q=-1 Return	'bail if unmatched tags
			n=data[p+1..q]
			data=data[q+1..]
'			Print "n="+n
			n=n.trim()
			If n[0..1]=("/")
				DebugLog "POP!"
				Exit
			EndIf
			If n[Len n-1..]="/"
				DebugLog "quickPOP!"
				Exit
			EndIf
			
			If n ParseXML n,element			
		EndIf	
EndRem	




Rem
extend TEntityView
	Field	host:THost
	Field	canvas:TGadget
	Field	timer:TTimer
	Field	entity:TEntity
	Field	model:TModel
	Field	yaw#,pitch#,dist#=-10
	Field	yawspeed#,pitchspeed#,zoomfactor#=1.0

		Local	stream:TStream		
		model=_model
		entity=_entity
		timer=CreateTimer(25)		
		host=plugin.host
		path=host.FullPath(file)		
		name=StripDir(path)
		host.AddPanel Self
		canvas=CreateCanvas(0,0,ClientWidth(panel),ClientHeight(panel),panel,0)
		canvas.SetLayout 1,1,1,1
		ActivateGadget canvas		
'		host.AddRecent path
		Return Self

	Function Open:TColladaView(plugin:TColladaPlugin,path$)
		Local	model:TModel	
		Local	entity:TEntity
		Local	view:TColladaView	
		Local	modeldir$,olddir$
		
		olddir=CurrentDir$()		
		modeldir=ExtractDir(RealPath(path))
		ChangeDir modeldir	
		model=LoadModel3DS( path )		
		If Not model 
			model=LoadModelB3D( path )
			entity=LoadEntity( path )
		EndIf
		ChangeDir olddir
		Print CurrentDir$()
		If Not model Return Null
		view=New TColladaView.Create(plugin,model,entity,path)		
		Return view
	End Function

EndRem


Rem
Type TAttribute
	Field name$
	Field value$
	Field data:Object
	Function Create:TAttribute(n$,v$)
		Local a:TAttribute=New TAttribute
		a.name=n
		a.value=v
		Return a
	End Function
End Type

Type TElement 
	Field name$="Root"
	Field attributes:TList=New TList
	Field content:TList=New TList
	Field value:Object
	Field parent:TElement
	Field tab$
	
EndRem


Rem
'		Local	brushes:TDataNode
'		Local	textures:TDataNode
		If entity.brushlist.Count()
			brushes=root.AddNode("Brushes")
			For Local brush:TB3DBrush=EachIn entity.brushlist
				brushes.AddNode brush.name
			Next
		EndIf
		If entity.texturelist.Count()
			textures=root.AddNode("Textures")
			For Local texture:TB3DTexture=EachIn entity.texturelist
				textures.AddNode texture.name
			Next			
		EndIf
		
		Local b3droot:TXMLNode
		
		b3droot=New TXMLNode.CreateEntityNode(Self,entity.root)
		b3droot.AttachKids		
		root.Append b3droot
		
		If EntityNode
			EntityNode.Sync(root)	
			root.Free
		Else
			EntityNode=root
		EndIf
		Return EntityNode
	End Method
EndRem

